package corewarsxxi.logic;

import corewarsxxi.logic.throwables.processJump;
import java.io.Serializable;

/**
 * Instruction <code>cmp</code> from Core Wars.
 * <p>Contains a static self to be used by all instances of MemoryCell.</p>
 * @version ICWS 88
 * @see     corewarsxxi.logic.OpCode
 * @author  Luís Fonseca, ei10139 @ FEUP
 */
public class cmp extends OpCode implements Serializable
{
    /** Core the instance.*/
    private transient Core c = super.getCore();

    /** Simplefied Singleton that provides access to a final static <code>cmp</code> instance.*/
    public static final cmp self = new cmp();

    /**
     * Private constructor of cmp.
     */
    private cmp() {}

    public void operation(MemoryField aField, MemoryField bField) throws processJump {
        if(AMImmediate.self.equals(aField.aMode))
        {
            int valA = aField.getValue();
            if(AMImmediate.self.equals(bField.aMode))
            {
                int valB = bField.getValue();
                MemoryCell mc = c.memArray.get(c.currentWarrior.processes.peek().offset);
                if(valB == valA)
                    throw new processJump(2);

                return;
            }
            int offset2 = bField.getValue();
            MemoryCell mc = c.memArray.get(offset2);
            if(mc.bField.value == valA)
                throw new processJump(2);
            
            return;
        }
        int offset = aField.getValue();
        if(AMImmediate.self.equals(bField.aMode))
        {
            MemoryCell mc = c.memArray.get(offset);
            int valB = mc.bField.getStoredValue();
            mc = c.memArray.get(c.currentWarrior.processes.peek().offset);
            if(mc.bField.value == valB)
                throw new processJump(2);
            
            return;
        }
        int offset2 = bField.getValue();
        MemoryCell mc = c.memArray.get(offset);
        int valA = mc.aField.getStoredValue();
        int valB = mc.bField.getStoredValue();
        mc = c.memArray.get(offset2);
        if(mc.aField.value == valA &&
           mc.bField.value == valB &&
           mc.opCode.equals(self))
            throw new processJump(2);
    }

    /**
     * Makes use of the Singleton pattern and returns the public static object.
     * @return it<i>self</i>.
     */
    @Override
    public OpCode getSelf() {
        return cmp.self;
    }

    /**
     * Overrides the default Object.toString() function.
     * @return Always returns "<code>cmp</code>".
     */
    @Override
    public String toString()
    {
        return "cmp";
    }
}